#!/usr/bin/env python
#
#       stats.py
#       
#       Copyright 2009 Brandon Invergo <brandon@brandoninvergo.com>
#       
#       This program is free software; you can redistribute it and/or modify
#       it under the terms of the GNU General Public License as published by
#       the Free Software Foundation; either version 2 of the License, or
#       (at your option) any later version.
#       
#       This program is distributed in the hope that it will be useful,
#       but WITHOUT ANY WARRANTY; without even the implied warranty of
#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#       GNU General Public License for more details.
#       
#       You should have received a copy of the GNU General Public License
#       along with this program; if not, write to the Free Software
#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#       MA 02110-1301, USA.

try:
    import pygtk
    #tell pyGTK, if possible, that we want GTKv2
    pygtk.require("2.0")
except:
    #Some distributions come with GTK2, but not pyGTK
    pass

try:
    import gtk
    import gtk.glade
    
except:
    print "You need to install pyGTK or GTKv2 ",
    print "or set your PYTHONPATH correctly."
    print "try: export PYTHONPATH=",
    print "/usr/local/lib/python2.2/site-packages/"
    sys.exit(1)
    
from gobject import TYPE_STRING
import Error_dialog
import Data_group
 
library_description = "Basic Statistics"
library_name = "stats"
R_library = ["stats"]
library_type = "analyses"
load_by_default = True 

gladefile = "libraries/stats.glade"
glade_gui = gtk.glade.XML(gladefile)
error = Error_dialog.Error_dialog()

lm_dialog = glade_gui.get_widget("lm_dialog")    
lm_dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
lm_dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)

ttest_dialog = glade_gui.get_widget("ttest_dialog")
ttest_dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
ttest_dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)

aic_dialog = glade_gui.get_widget("aic_dialog")
aic_dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
aic_dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)

alias_dialog = glade_gui.get_widget("alias_dialog")
alias_dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
alias_dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)

bartlett_dialog = glade_gui.get_widget("bartlett_dialog")
bartlett_dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
bartlett_dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)

anova_dialog = glade_gui.get_widget("anova_dialog")
anova_dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
anova_dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)

pearson_dialog = glade_gui.get_widget("pearson_dialog")
pearson_dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
pearson_dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)

fisher_dialog = glade_gui.get_widget("fisher_dialog")
fisher_dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
fisher_dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)

fivenum_dialog = glade_gui.get_widget("fivenum_dialog")
fivenum_dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
fivenum_dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)

fligner_dialog = glade_gui.get_widget("fligner_dialog")
fligner_dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
fligner_dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)

kruskal_dialog = glade_gui.get_widget("kruskal_dialog")
kruskal_dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
kruskal_dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)

mcnemar_dialog = glade_gui.get_widget("mcnemar_dialog")
mcnemar_dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
mcnemar_dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)

median_dialog = glade_gui.get_widget("median_dialog")
median_dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
median_dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)

mean_dialog = glade_gui.get_widget("mean_dialog")
mean_dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
mean_dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)

sd_dialog = glade_gui.get_widget("sd_dialog")
sd_dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
sd_dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)

prop_dialog = glade_gui.get_widget("prop_dialog")
prop_dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
prop_dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
    
def lm(data_group):
    command = {}
    member_dict = data_group.member_dict
    memb_list = data_group.member_list
    
    num_factors = member_dict.get("Fixed Factor")
    num_covariates = member_dict.get("Covariate")
    
    if num_factors > 0 and num_covariates == None:
        analysis_type = "ANOVA"
    elif num_factors > 0 and num_covariates > 0:
        analysis_type = "ANCOVA"
    else:
        analysis_type = "Linear Regression"
        
    lm_label = glade_gui.get_widget("lm_framelabel")
    lm_label.set_markup(analysis_type.join(["<b>", "</b>"]))
    
    lm_model_list = []
    factors = []
    for member in memb_list:
        if member.role == "Response":
            response = member.id
            family = member.aux
        elif member.role == "Fixed Factor" or member.role == "Covariate":
            factors.append(member.id)
    
    model_hbox = glade_gui.get_widget("lm_model_hbox")
    model_hbox_children = model_hbox.get_children()
    if len(model_hbox_children) == 2:
        model_hbox.remove(model_hbox_children[1])
    lm_model_sub_hbox = gtk.HBox(spacing = 10)
    
    response_label = gtk.Label(response)
    lm_model_sub_hbox.pack_start(response_label)
    response_label.show()
    
    model_by_label = gtk.Label("~")
    lm_model_sub_hbox.pack_start(model_by_label)
    model_by_label.show()
    
    lm_buttonbox = glade_gui.get_widget("lm_buttonbox")
    buttonbox_children = lm_buttonbox.get_children()
    if len(buttonbox_children) > 1:
        lm_buttonbox.remove(buttonbox_children[-1])
    full_factor_list = lm_make_ints(factors)
    full_factor_list.sort(len_compare)
    term_combo_list = gtk.ListStore(TYPE_STRING)
    term_combo = gtk.ComboBox(term_combo_list)
    term_combo_cell = gtk.CellRendererText()
    term_combo.pack_start(term_combo_cell, False)
    term_combo.add_attribute(term_combo_cell, 'text', 0)  
    term_combo.show()
    lm_buttonbox.pack_start(term_combo)    
    
    lm_set_term_combo(term_combo, full_factor_list, lm_model_sub_hbox)
    
    lm_add_button = glade_gui.get_widget("lm_add_button")
    lm_add_button.connect("clicked", on_lm_add, term_combo, full_factor_list,\
        lm_model_sub_hbox)
    lm_remove_button = glade_gui.get_widget("lm_remove_button")
    lm_remove_button.connect("clicked", on_lm_remove, term_combo, \
        full_factor_list, lm_model_sub_hbox)
    
    model_hbox.pack_end(lm_model_sub_hbox)
    lm_model_sub_hbox.show()
    
    link_hbox = glade_gui.get_widget("lm_link_hbox")
    link_hbox_children = link_hbox.get_children()
    if len(link_hbox_children) == 2:
        link_hbox.remove(model_hbox_children[1])
    if family != "Normal":
        link_hbox.set_child_visible(True)
        link_combo = gtk.combo_box_new_text()
        if family == "Binomial" or family == "Quasibinomial":
            link_combo.append_text("Logit")
            link_combo.append_text("Probit")
            link_combo.append_text("Cauchit")
            link_combo.append_text("Log")
            link_combo.append_text("Cloglog")
        if family == "Poisson" or family == "Quasipoisson":
            link_combo.append_text("Log")
            link_combo.append_text("Identity")
            link_combo.append_text("Sqrt")
        if family == "Gamma":
            link_combo.append_text("Inverse")
            link_combo.append_text("Identity")
            link_combo.append_text("Log")
        if family == "Inverse Gaussian":
            link_combo.append_text("1/mu^2")
            link_combo.append_text("Inverse")
            link_combo.append_text("Identity")
            link_combo.append_text("Log")
        link_combo.set_active(0)
        link_hbox.pack_end(link_combo)
        link_combo.show()
        link_hbox.show()        
    else:
        link_hbox.hide()

    na_action = glade_gui.get_widget("lm_naaction")
    na_action.set_active(True)
    subset = glade_gui.get_widget("lm_subset_string")
    subset.set_text("")
    subset_check = glade_gui.get_widget("lm_usesubset")
    subset_check.set_active(False)
    
    response = lm_dialog.run()   
    
    if response == gtk.RESPONSE_OK:
        model = ""
        model_children = lm_model_sub_hbox.get_children()
        for child in model_children:
            model = model + child.get_text()
        
        group_id = data_group.id_str
        model_name = group_id + "linear.model"
        
        if family != "Normal":
            link_str = link_combo.get_active_text().lower()
            if family != "Gamma":
                family_format = family.lower()
            else:
                family_format = family
            family_format = family_format.replace(" ", ".")
            family_str = ",family=%s(\"%s\")"%(family_lower, link_str)
        
        na_action = glade_gui.get_widget("lm_naaction").get_active()
        if na_action == True:
            na_action_str = ",na.action = na.omit"
        else:
            na_action_str = ""
            
        use_subset = glade_gui.get_widget("lm_usesubset").get_active()
        if use_subset == True:
            subset = glade_gui.get_widget("lm_subset_string").get_text()
            subset_str = ",subset=" + subset
        else:
            subset_str = ""
        
        if family == "Normal":    
            model_command_list = [model_name, "<-lm(", model, na_action_str, \
                subset_str, ")"]
            model_command = "".join(model_command_list)
            lm_command = "summary.lm(%s)"%model_name
        else:
            model_command_list = [model_name, "<-glm(", model, family_str, \
                na_action_str, subset_str, ")"]
            model_command = "".join(model_command_list)
            lm_command = "summary.glm(%s)"%model_name
        cleanup_command = ""
        command["pre"] = model_command
        command["main"] = lm_command
        command["post"] = cleanup_command
    else:
        command["pre"] = ""
        command["main"] = ""
        command["post"] = ""
    lm_dialog.hide()
    return command
    
def on_lm_usesubset(widget):
    use_subset = glade_gui.get_widget("lm_usesubset").get_active()
    subset_entry = glade_gui.get_widget("lm_subset_string")
    if use_subset == True:
        subset_entry.set_sensitive(True)
    else:
        subset_entry.set_sensitive(False)
        
def on_lm_add(widget, combo, factors, model_hbox):
    combo_list = combo.get_model()
    active_iter = combo.get_active_iter()
    active_term = combo_list.get_value(active_iter, 0)
    term_label = gtk.Label(active_term)
    term_label.show()
    model_hbox.pack_start(term_label)
    
    if factors.count(active_term) > 0:
        factors.remove(active_term)
        
    lm_set_term_combo(combo, factors, model_hbox)
   
def lm_make_ints(factors):
    if len(factors) == 1:
        return factors
    if len(factors) == 2:
        interaction = ":".join([factors[0], factors[1]])
        fact_copy = list(factors)
        fact_copy.append(interaction)
        return fact_copy
    rest_ints = lm_make_ints(factors[1:])
    new_interactions = [":".join([factors[0], rest]) for rest in rest_ints]
    new_interactions.insert(0, factors[0])
    new_interactions.extend(rest_ints)
    return new_interactions
    
def len_compare(a, b):
    return len(a) - len(b)
    

def on_lm_remove(widget, combo, factors, model_hbox):
    model_hbox_children = model_hbox.get_children()
    if len(model_hbox_children) > 2:
        term = model_hbox_children[-1].get_text()
        model_hbox.remove(model_hbox_children[-1])
    if term not in ["*", "+", "-", "(", ")"]:
        factors.append(term)
        factors.sort(len_compare)
    combo_list = combo.get_model()
    lm_set_term_combo(combo, factors, model_hbox)
        
def lm_set_term_combo(combo, factors, model_hbox):
    model_hbox_children = model_hbox.get_children()
    last_term = model_hbox_children[-1].get_text()
    combo_list = combo.get_model()
    combo_list.clear()
    
    if last_term in ["~", "*", "+", "-"]:
        for factor in factors:
            combo_list.append([factor])
        combo_list.append(["("])
    else:
        combo_list.append(["*"])
        combo_list.append(["+"])
        combo_list.append(["-"])
        combo_list.append([")"])
    
    combo.set_active(0)
    

def t_test(data_group):    
    command = {}
    member_dict = data_group.member_dict
    member_list = data_group.member_list
    
    if member_dict.get("Sample Data") == 2:
        use_model = False
        group_x = member_list[0].id
        group_y = member_list[1].id
        greater_label = " > ".join([group_x, group_y])
        less_label = " < ".join([group_x, group_y])
        glade_gui.get_widget("ttest_greater_radio").set_label(greater_label)
        glade_gui.get_widget("ttest_less_radio").set_label(less_label)
    else:
        use_model = True
        for member in member_list:
            if member.role == "Fixed Factor":
                levels = member.aux
                greater_label = " > ".join([levels[0], levels[1]])
                less_label = " < ".join([levels[0], levels[1]])
                glade_gui.get_widget("ttest_greater_radio").set_label(greater_label)
                glade_gui.get_widget("ttest_less_radio").set_label(less_label)
                
    ttest_usesubset = glade_gui.get_widget("ttest_usesubset")
    ttest_usesubset.set_active(False)
    ttest_usesubset_str = glade_gui.get_widget("ttest_usesubset_string")
    ttest_usesubset_str.set_text("")
    ttest_naaction = glade_gui.get_widget("ttest_naaction")
    ttest_naaction.set_active(True)
    
    response = ttest_dialog.run()
    
    if response == gtk.RESPONSE_OK:
        althyp_group = glade_gui.get_widget("ttest_twosided_radio").get_group()
        for radio in althyp_group:
            if radio.get_active() == True:
                if radio.get_name() == "ttest_twosided_radio":
                    alt_command = ", alternative = \"two.sided\""
                    break
                if radio.get_name() == "ttest_greater_radio":
                    alt_command = ", alternative = \"greater\""
                    break
                else:
                    alt_command = ", alternative = \"less\""
        
        confidence = glade_gui.get_widget("ttest_confidence").get_text()
        if confidence == "" or (float(confidence) < 0 or float(confidence) > 1):
            self.error.show_error("Error", "You must enter a confidence level (0-1)")
            ttest_dialog.hide()
            return ttest(data_group)
        confidence_command = ", conf.level = %s"%confidence
            
        paired = glade_gui.get_widget("ttest_paired").get_active()
        if paired:
            paired_command = ", paired = TRUE"
        else:
            paired_command = ""
        
        varequal = glade_gui.get_widget("ttest_varequal").get_active()
        if varequal:
            varequal_command = ", var.equal = TRUE"
        else:
            varequal_command = ""
        
        naaction = glade_gui.get_widget("ttest_naaction").get_active()
        if naaction:
            naaction_command = ", na.action = na.omit"
        else:
            naaction_command = ""
        
        subset = glade_gui.get_widget("ttest_usesubset").get_active()
        if subset:
            subset_str = glade_gui.get_widget("ttest_usesubset_string").get_text()
            if subset_str == "":
                self.error.show_error("Error", "You must enter a logical subset string.")
                ttest_dialog.hide()
                return ttest(data_group)
            subset_command = ", subset = %s"%subset_str
        else:
            subset_command = ""
        
        if use_model == False:
            group_x = member_list[0].id
            group_y = member_list[1].id
            target_command = "%s, %s"%(group_x, group_y)
        else:
            for member in member_list:
                if member.role == "Response" or member.role == "Sample Data":
                    response = member.id
                elif member.role == "Fixed Factor":
                    factor = member.id
            target_command = "%s ~ %s"%(response, factor)
        
        ttest_params = "".join([target_command, alt_command, confidence_command,\
            paired_command, varequal_command, naaction_command, subset_command])
        ttest_command = "t.test(%s)"%ttest_params
        command["pre"] = ""
        command["main"] = ttest_command
        command["post"] = ""
        
    else:
        command["pre"] = ""
        command["main"] = ""
        command["post"] = ""
    
    ttest_dialog.hide()
    return command
    
def on_ttest_usesubset(checkbutton):
    use_subset = checkbutton.get_active()
    if use_subset:
        glade_gui.get_widget("ttest_usesubset_string").set_sensitive(True)
    else:
        glade_gui.get_widget("ttest_usesubset_string").set_sensitive(False)

def aic(data_group):
    command = {}
    
    group_members = data_group.member_list
    for member in group_members:
        if member.role == "Linear Model":
            model = member.id
            break
    
    if model == None:
        error.show_error("AIC (stats)", "Model missing")
        command["pre"] = ""
        command["main"] = ""
        command["post"] = ""
        return command
    
    aic_k_entry = glade_gui.get_widget("aic_k_entry")
    aic_k_entry.set_text("2")

    aic_scale_entry = glade_gui.get_widget("aic_scale_entry")
    aic_scale_entry.set_text("0")
    
    response = aic_dialog.run()
    
    if response == gtk.RESPONSE_OK:
        aic_k = aic_k_entry.get_text()
        if aic_k == "":
            error.show_error("AIC (stats)", "You must provide a k value (k=2 for standard AIC)")
            aic_dialog.hide()
            return aic(data_group)
        try:
            int(aic_k)
        except:
            error.show_error("AIC (stats)", "You must provide an integer value for k")
            aic_dialog.hide()
            return aic(data_group)
        if int(aic_k) < 0:
            error.show_error("AIC (stats)", "k must be greater than zero")
            aic_dialog.hide()
            return aic(data_group)
        k_str = ", k=%s"%aic_k
        
        aic_scale = aic_scale_entry.get_text()
        if aic_scale == "":
            scale_str = ""
        else:
            try:
                int(aic_scale)
            except:
                error.show_error("AIC (stats)", "You must provide an integer value for the scale")
                aic_dialog.hide()
                return aic(data_group)
            if int(aic_scale) < 0:
                error.show_error("AIC (stats)", "The scale must be greater than zero")
                aic_dialog.hide()
                return aic(data_group)
            scale_str = ", scale=%s"%aic_scale
        
        aic_command = "AIC(%s%s%s)"%(model, scale_str, k_str)
        command["pre"] = ""
        command["main"] = aic_command
        command["post"] = ""
    else:
        command["pre"] = ""
        command["main"] = ""
        command["post"] = ""
    aic_dialog.hide()
    return command
    
def alias(data_group):
    command = {}

    group_members = data_group.member_list
    for member in group_members:
        if member.role == "Linear Model":
            model = member.id
            break
    
    if model == None:
        error.show_error("Alias (stats)", "Model missing")
        command["pre"] = ""
        command["main"] = ""
        command["post"] = ""
        return command
    
    alias_complete_check = glade_gui.get_widget("alias_complete_check")
    alias_complete_check.set_active(True)
    
    alias_partial_check = glade_gui.get_widget("alias_partial_check")
    alias_partial_check.set_active(False)
    
    response = alias_dialog.run()
    
    if response == gtk.RESPONSE_OK:
        alias_complete = alias_complete_check.get_active()
        alias_partial = alias_partial_check.get_active()
        
        alias_complete_str = str(alias_complete).upper()
        alias_partial_str = str(alias_partial).upper()
        
        alias_command = "alias(%s, complete=%s, partial=%s)"%(model, alias_complete_str,\
            alias_partial_str)
        command["pre"] = ""
        command["main"] = alias_command
        command["post"] = ""
    else:
        command["pre"] = ""
        command["main"] = ""
        command["post"] = ""
    alias_dialog.hide()
    return command
    
def on_bartlett_usesubset(widget):
    use_subset = lm_dialog.get_widget("bartlett_usesubset").get_active()
    subset_entry = lm_dialog.get_widget("bartlett_subset_string")
    if use_subset == True:
        subset_entry.set_sensitive(True)
    else:
        subset_entry.set_sensitive(False)

def bartlett(data_group):
    command = {}
    
    group_members = data_group.member_list
    group_dict = data_group.member_dict
    
    if group_dict.get("Fixed Factor") == 1:
        for member in group_members:
            if member.role == "Fixed Factor":
                factor = member.id
            elif member.role == "Response" or member.role == "Sample Data":
                data = member.id
    
        if factor == None:
            error.show_error("Bartlett Test (stats)", "Factor missing")
            command["pre"] = ""
            command["main"] = ""
            command["post"] = ""
            return command
        
        use_factor = True
        
    else:
        sample_list = []
        for member in group_members:
            if member.role == "Sample Data":
                sample_list.append(member.id)
        
        use_factor = False
    
    bartlett_usesubset_check = glade_gui.get_widget("bartlett_usesubset")
    bartlett_usesubset_check.set_active(False)
    bartlett_usesubset_entry = glade_gui.get_widget("bartlett_usesubset_string")
    bartlett_usesubset_entry.set_text("")
    bartlett_naaction_check = glade_gui.get_widget("bartlett_naaction")
    bartlett_naaction_check.set_active(True)
    
    response = bartlett_dialog.run()
    
    if response == gtk.RESPONSE_OK:
        bartlett_naaction = bartlett_naaction_check.get_active()
        if bartlett_naaction:
            naaction = ", naaction = na.omit"
        else:
            naaction = ""
        
        bartlett_usesubset = bartlett_usesubset_check.get_active()
        if bartlett_usesubset:
            bartlett_usesubset_str = bartlett_usesubset_entry.get_text()
            if bartlett_usesubset_str == "":
                error.show_error("Bartlett Test (stats)", "You must enter a subset")
                bartlett_dialog.hide()
                return bartlett(data_group)
            usesubset = ", subset=" + bartlett_usesubset_str
        else:
            usesubset = ""
        
        if use_factor:
            bartlett_command = "bartlett.test(%s,%s%s%s)"%(data, factor, \
                naaction, usesubset)
        else:
            sample_list_str = ",".join(sample_list)
            sample_list_cmd = "list(%s)"%sample_list_str
            bartlett_command = "bartlett.test(%s%s%s)"%(sample_list_cmd,\
                naaction, usesubset)
        command["pre"] = ""
        command["main"] = bartlett_command
        command["post"] = ""
    else:
        command["pre"] = ""
        command["main"] = ""
        command["post"] = ""
    bartlett_dialog.hide()
    return command
    
def anova(data_group):
    command = {}
    
    response = anova_dialog.run()
    
    if response == gtk.RESPONSE_OK:
        model_list = []
        for member in data_group.member_list:
            if member.role == "Linear Model":
                model_list.append(member.id)
                
        if len(model_list) == 0:
            error.show_error("ANOVA (stats)", "Model missing")
            command["pre"] = ""
            command["main"] = ""
            command["post"] = ""
            anova_dialog.hide()
            return command
            
        model_str = ",".join(model_list)
        
        command["pre"] = ""
        command["main"] = "anova(%s)"%model_str
        command["post"] = ""
    else:
        command["pre"] = ""
        command["main"] = ""
        command["post"] = ""
    anova_dialog.hide()
    return command
    
def pearson(data_group):
    command = {}
    
    group_dict = data_group.member_dict
    group_members = data_group.member_list
    
    if group_dict.get("Counts") == None:
        use_factors = True
        factors = []
        for member in group_members:
            if member.role == "Fixed Factor":
                factors.append(member.id)
            
        if len(factors) > 2:
            error.show_error("Chi-squared test (stats)", "Too many factors")
            command["pre"] = ""
            command["main"] = ""
            command["post"] = ""
            return command
    else:
        use_factors = False
        counts = []
        probs = None
        for member in group_members:
            if member.role == "Counts":
                counts.append(member.id)
            elif member.role == "Probabilities":
                probs = member.id
                
    correct_check = glade_gui.get_widget("pearson_correct_check")
    correct_check.set_active(True)
    simulate_check = glade_gui.get_widget("pearson_simulate_check")
    simulate_check.set_active(False)
    b_entry = glade_gui.get_widget("pearson_b_entry")
    b_entry.set_text("2000")
    b_entry.set_sensitive(False)
    
    response = pearson_dialog.run()
    
    if response == gtk.RESPONSE_OK:
        correct = correct_check.get_active()
        if correct:
            correct_str = ", correct=TRUE"
        else:
            correct_str = ", correct=FALSE"
            
        simulate = simulate_check.get_active()
        if simulate:
            simulate_str = ", simulate.p.value=TRUE"
            b = b_entry.get_text()
            if b == "":
                error.show_error("Chi-squared test (stats)", "The number of Monte Carlo replicates must be specified")
                pearson_dialog.hide()
                return chisq(data_group)
            b_str = ", B=%s"%b
        else:
            simulate_str = ", simulate.p.value=FALSE"
            b_str = ""
        
        if use_factors:
            if len(factors) == 1:
                fact_str = "table(%s)"%factors[0]
            else:
                fact_str = "%s, %s"%(factors[0], factors[1])
            
            command["pre"] = ""
            command["main"] = "chisq.test(%s%s%s%s)"%(fact_str, correct_str, \
                simulate_str, b_str)
            command["post"] = ""
        else:
            if len(counts) == 1:
                count_matrix_str = "matrix(%s)"%counts[0]
            else:
                count_str = ",".join(counts)
                count_matrix_str = "matrix(c(%s), ncol=%i)"%(count_str, len(counts))
            if probs != None:
                probs_str = ", p=%s"%probs
            else:
                probs_str = ""
            
            command["pre"] = ""
            command["main"] = "chisq.test(%s%s%s%s%s)"%(count_matrix_str, correct_str,\
                probs_str, simulate_str, b_str)
            command["post"] = ""
    else:
        command["pre"] = ""
        command["main"] = ""
        command["post"] = ""
    pearson_dialog.hide()
    return command

def on_pearson_simulate(widget):
    simulate = glade_gui.get_widget("pearson_simulate_check").get_active()
    b_entry = glade_gui.get_widget("pearson_b_entry")
    correct_check = glade_gui.get_widget("pearson_correct_check")
    if simulate:
        b_entry.set_sensitive(True)
        correct_check.set_sensitive(False)
    else:
        b_entry.set_sensitive(False)
        correct_check.set_sensitive(True)
        
def fisher(data_group):
    command = {}
    
    group_dict = data_group.member_dict
    group_members = data_group.member_list
    
    if group_dict.get("Counts") == None:
        use_factors = True
        factors = []
        for member in group_members:
            if member.role == "Fixed Factor":
                factors.append(member.id)
            
        if len(factors) > 2:
            error.show_error("Fisher Test (stats)", "Too many factors")
            command["pre"] = ""
            command["main"] = ""
            command["post"] = ""
            return command
    else:
        use_factors = False
        counts = []
        for member in group_members:
            if member.role == "Counts":
                counts.append(member.id)
                
    twosided_radio = glade_gui.get_widget("fisher_twosided_radio")
    twosided_radio.set_active(True)
    confint_check = glade_gui.get_widget("fisher_confint_check")
    confint_check.set_active(True)
    conflevel_entry = glade_gui.get_widget("fisher_conflevel_entry")
    conflevel_entry.set_text("0.95")
    conflevel_entry.set_sensitive(True)
    or_entry = glade_gui.get_widget("fisher_or_entry")
    or_entry.set_text("1")
    hybrid_check = glade_gui.get_widget("fisher_hybrid_check")
    hybrid_check.set_active(False)
    simulate_check = glade_gui.get_widget("fisher_simulate_check")
    simulate_check.set_active(False)
    b_entry = glade_gui.get_widget("fisher_b_entry")
    b_entry.set_text("2000")
    b_entry.set_sensitive(False)
    workspace_entry = glade_gui.get_widget("fisher_workspace_entry")
    workspace_entry.set_text("200000")
    
    response = fisher_dialog.run()
    
    if response == gtk.RESPONSE_OK:
        althyp_radio_group = twosided_radio.get_group()
        for radio in althyp_radio_group:
            if radio.get_active() == True:
                if radio.get_name() == "fisher_twosided_radio":
                    althyp_str = ", alternative=\"two.sided\""
                elif radio.get_name() == "fisher_greater_radio":
                    althyp_str = ", alternative=\"greater\""
                else:
                    althyp_str = ", alternative=\"less\""
                break
        
        confint = confint_check.get_active()
        if confint:
            confint_str = ", conf.int=TRUE"
            conflevel = conflevel_entry.get_text()
            if conflevel == "":
                error.show_error("Fisher Test (stats)", "You must enter a confidence level.")
                fisher_dialog.hide()
                return fisher(data_group)
            try:
                float(conflevel)
            except:
                error.show_error("Fisher Test (stats)", "Confidence level must be a value between 0 and 1.")
                fisher_dialog.hide()
                return fisher(data_group)
            if float(conflevel) > 1 or float(conflevel) < 0:
                error.show_error("Fisher Test (stats)", "Confindence level must be a value between 0 and 1.")
                fisher_dialog.hide()
                return fisher(data_group)            
            conflevel_str = ", conf.level=%s"%conflevel
        else:
            confint_str = ", conf.int=FALSE"
            conflevel_str = ""
            
        odds_ratio = or_entry.get_text()
        if odds_ratio == "":
            error.show_error("Fisher Test (stats)", "You must enter an odds ratio")
            fisher_dialog.hide()
            return fisher(data_group)
        try:
            float(odds_ratio)
        except:
            error.show_error("Fisher Test (stats)", "The odds ratio must be a value greater than 0.")
            fisher_dialog.hide()
            return fisher(data_group)
        if float(odds_ratio) < 0:
            error.show_error("Fisher Test (stats)", "The odds ratio must be a value greater than 0.")
            fisher_dialog.hide()
            return fisher(data_group)
        or_str = ", or=%s"%odds_ratio
            
        hybrid = hybrid_check.get_active()
        if hybrid:
            hybrid_str = ", hybrid=TRUE"
        else:
            hybrid_str = ", hybrid=FALSE"
            
        simulate = simulate_check.get_active()
        if simulate:
            simulate_str = ", simulate.p.value=TRUE"
            b = b_entry.get_text()
            if b == "":
                error.show_error("Fisher Test (stats)", "The number of Monte Carlo replicates must be specified")
                fisher_dialog.hide()
                return fisher(data_group)
            try:
                int(b)
            except:
                error.show_error("Fisher Test (stats)", "The number of replicates must be an integer")
                fisher_dialog.hide()
                return fisher(data_group)
            if int(b) < 0:
                error.show_error("Fisher Test (stats)", "The number of replicates must be greater than zero.")
                fisher_dialog.hide()
                return fisher(data_group)
            b_str = ", B=%s"%b
        else:
            simulate_str = ", simulate.p.value=FALSE"
            b_str = ""
            
        workspace = workspace_entry.get_text()
        if workspace == "":
            error.show_error("Fisher Test (stats)", "You must enter a workspace size")
            fisher_dialog.hide()
            return fisher(data_group)
        try:
            int(workspace)
        except:
            error.show_error("Fisher Test (stats)", "Workspace size must be a positive integer")
            fisher_dialog.hide()
            return fisher(data_group)
        if int(workspace) < 0:
            error.show_error("Fisher Test (stats)", "Workspace size must be a positive integer")
            fisher_dialog.hide()
            return fisher(data_group)
        workspace_str = ", workspace=%s"%workspace
        
        if use_factors:
            subj_str = "%s, %s"%(factors[0], factors[1])
        else:
            subj_str = "matrix(c("
            for count in counts:
                if subj_str[-1] == "(":
                    new_count = count
                else:
                    new_count = "," + count
                subj_str = subj_str + new_count
            num_counts = len(counts)
            subj_str_end = "), ncol=%i"%num_counts
            subj_str_end = subj_str_end + ")"
            subj_str = subj_str + subj_str_end
                        
        command["pre"] = ""
        command["main"] = "fisher.test(%s%s%s%s%s%s%s%s%s)"%(subj_str, \
            althyp_str, confint_str, conflevel_str, or_str, hybrid_str, \
            simulate_str, b_str, workspace_str)
        command["post"] = ""

    else:
        command["pre"] = ""
        command["main"] = ""
        command["post"] = ""
    fisher_dialog.hide()
    return command

def on_fisher_simulate(widget):
    simulate = glade_gui.get_widget("fisher_simulate_check").get_active()
    b_entry = glade_gui.get_widget("fisher_b_entry")
    if simulate:
        b_entry.set_sensitive(True)
    else:
        b_entry.set_sensitive(False)
        
def on_fisher_confint(widget):
    confint = glade_gui.get_widget("fisher_confint_check").get_active()
    conflevel_entry = glade_gui.get_widget("fisher_conflevel_entry")
    if confint:
        conflevel_entry.set_sensitive(True)
    else:
        conflevel_entry.set_sensitive(False)

def fivenum(data_group):
    command = {}
    
    for member in data_group.member_list:
        if member.role == "Sample Data":
            x = member.id
        
    narm_check = glade_gui.get_widget("fivenum_narm")
    narm_check.set_active(True)
    
    response = fivenum_dialog.run()
    
    if response == gtk.RESPONSE_OK:
        narm = str(narm_check.get_active()).upper()
        narm_str = ", na.rm=%s"%narm
        
        command["pre"] = ""
        command["main"] = "fivenum(%s%s)"%(x, narm_str)
        command["post"] = ""
    else:
        command["pre"] = ""
        command["main"] = ""
        command["post"] = ""
    fivenum_dialog.hide()
    return command
    
def fligner(data_group):
    command = {}
    
    if data_group.member_dict.get("Fixed Factor") == 1:
        use_factor = True
        for member in data_group.member_list:
            if member.role == "Response" or member.role == "Sample Data":
                data = member.id
            elif member.role == "Fixed Factor":
                factor = member.id
    else:
        use_factor = False
        data = []
        for member in data_group.member_list:
            if member.role == "Sample Data":
                data.append(member.id)
    
    response = fligner_dialog.run()
    
    if response == gtk.RESPONSE_OK:
        if use_factor:
            command["pre"] = ""
            command["main"] = "fligner.test(%s, %s)"%(data, factor)
            command["post"] = ""
            print command.get("main")
        else:
            command["pre"] = ""
            data_list = ",".join(data)
            command["main"] = "fligner.test(list(%s))"%data_list
            command["post"] = ""
    else:
        command["pre"] = ""
        command["main"] = ""
        command["post"] = ""
    fligner_dialog.hide()
    return command
    
def kruskal(data_group):
    command = {}
    
    if data_group.member_dict.get("Fixed Factor") == 1:
        use_factor = True
        for member in data_group.member_list:
            if member.role == "Response" or member.role == "Sample Data":
                data = member.id
            elif member.role == "Fixed Factor":
                factor = member.id
    else:
        use_factor = False
        data = []
        for member in data_group.member_list:
            if member.role == "Sample Data":
                data.append(member.id)
    
    response = kruskal_dialog.run()
    
    if response == gtk.RESPONSE_OK:
        if use_factor:
            command["pre"] = ""
            command["main"] = "kruskal.test(%s, %s)"%(data, factor)
            command["post"] = ""
            print command.get("main")
        else:
            command["pre"] = ""
            data_list = ",".join(data)
            command["main"] = "kruskal.test(list(%s))"%data_list
            command["post"] = ""
    else:
        command["pre"] = ""
        command["main"] = ""
        command["post"] = ""
    kruskal_dialog.hide()
    return command

def mcnemar(data_group):
    command = {}
    
    group_dict = data_group.member_dict
    group_members = data_group.member_list
    
    if group_dict.get("Counts") == None:
        use_factors = True
        factors = []
        for member in group_members:
            if member.role == "Fixed Factor":
                factors.append(member.id)
            
        if len(factors) > 2:
            error.show_error("McNemar's Chi-Squared Test (stats)", "Too many factors")
            command["pre"] = ""
            command["main"] = ""
            command["post"] = ""
            return command
    else:
        use_factors = False
        counts = []
        probs = None
        for member in group_members:
            if member.role == "Counts":
                counts.append(member.id)
                
    correct_check = glade_gui.get_widget("mcnemar_correct_check")
    correct_check.set_active(True)
    
    response = mcnemar_dialog.run()
    
    if response == gtk.RESPONSE_OK:
        correct = correct_check.get_active()
        if correct:
            correct_str = ", correct=TRUE"
        else:
            correct_str = ", correct=FALSE"
        
        if use_factors:
            fact_str = "%s, %s"%(factors[0], factors[1])
            
            command["pre"] = ""
            command["main"] = "mcnemar.test(%s%s)"%(fact_str, correct_str)
            command["post"] = ""
        else:
            count_str = ",".join(counts)
            count_matrix_str = "matrix(c(%s), ncol=%i)"%(count_str, len(counts))
            
            command["pre"] = ""
            command["main"] = "mcnemar.test(%s%s)"%(count_matrix_str, correct_str)
            command["post"] = ""
    else:
        command["pre"] = ""
        command["main"] = ""
        command["post"] = ""
    mcnemar_dialog.hide()
    return command
    
def median(data_group):
    command = {}
    
    for member in data_group.member_list:
        if member.role == "Sample Data" or member.role == "Response":
            data = member.id
            break
    
    narm_check = glade_gui.get_widget("median_narm_check")
    narm_check.set_active(True)
    
    response = median_dialog.run()
    
    if response == gtk.RESPONSE_OK:
        narm = narm_check.get_active()
        narm_str = ", na.rm=%s"%str(narm).upper()
        
        command["pre"] = ""
        command["main"] = "median(%s%s)"%(data, narm_str)
        command["post"] = ""
    else:
        command["pre"] = ""
        command["main"] = ""
        command["post"] = ""
    median_dialog.hide()
    return command
    
def mean(data_group):
    command = {}
    
    for member in data_group.member_list:
        if member.role == "Sample Data" or member.role == "Response":
            data = member.id
            break
    
    narm_check = glade_gui.get_widget("mean_narm_check")
    narm_check.set_active(True)
    
    trim_entry = glade_gui.get_widget("mean_trim_entry")
    trim_entry.set_text("0")
    
    response = mean_dialog.run()
    
    if response == gtk.RESPONSE_OK:
        narm = narm_check.get_active()
        narm_str = ", na.rm=%s"%str(narm).upper()
        
        trim = trim_entry.get_text()
        if trim == "":
            error.show_error("Mean (stats)", "Trim must have a value between 0 and 0.5")
            mean_dialog.hide()
            return mean(data_group)
        try: 
            float(trim)
        except:
            error.show_error("Mean (stats)", "Trim must have a value between 0 and 0.5")
            mean_dialog.hide()
            return mean(data_group)
        if float(trim) < 0 or float(trim) > 0.5:
            error.show_error("Mean (stats)", "Trim must have a value between 0 and 0.5")
            mean_dialog.hide()
            return mean(data_group)
        trim_str = ", trim=%s"%trim
        
        command["pre"] = ""
        command["main"] = "mean(%s%s%s)"%(data,trim_str,narm_str)
        command["post"] = ""
    else:
        command["pre"] = ""
        command["main"] = ""
        command["post"] = ""
    mean_dialog.hide()
    return command
    
def sd(data_group):
    command = {}
    
    for member in data_group.member_list:
        if member.role == "Sample Data" or member.role == "Response":
            data = member.id
            break
    
    narm_check = glade_gui.get_widget("sd_narm_check")
    narm_check.set_active(True)
    
    response = sd_dialog.run()
    
    if response == gtk.RESPONSE_OK:
        narm = narm_check.get_active()
        narm_str = ", na.rm=%s"%str(narm).upper()
        
        command["pre"] = ""
        command["main"] = "sd(%s%s)"%(data, narm_str)
        command["post"] = ""
    else:
        command["pre"] = ""
        command["main"] = ""
        command["post"] = ""
    sd_dialog.hide()
    return command
    
def prop(data_group):
    command = {}
    
    data = []
    probs = ""
    
    for member in data_group.member_list:
        if member.role == "Counts":
            data.append(member)
        elif member.role == "Probabilities":
            probs = member.id
            
    trials_radio = glade_gui.get_widget("prop_trials_radio")
    trials_radio.set_active(True)
    twosided_radio = glade_gui.get_widget("prop_twosided_radio")
    twosided_radio.set_active(True)
    conflevel_entry = glade_gui.get_widget("prop_conflevel_entry")
    conflevel_entry.set_text("0.95")
    correct_check = glade_gui.get_widget("prop_correct_check")
    correct_check.set_active(True)
            
    response = prop_dialog.run()
    
    if response == gtk.RESPONSE_OK:
        data1 = data[0].id
        data2 = data[1].id
        use_trials = trials_radio.get_active()
        if use_trials:
                setup_str = "if(%s[1] < %s[1]){succ <- %s; trials <- %s} else {succ <- %s; trials <- %s}"\
                    %(data1, data2, data1, data2, data2, data1)
                cleanup_str = "rm(succ); rm(trials)"
        else:
            setup_str = ""
            
        if probs != "":
            prob_str = ", p=%s"%probs
        else:
            prob_str = ""
        
        althyp_radio_group = twosided_radio.get_group()
        for radio in althyp_radio_group:
            if radio.get_active() == True:
                if radio.get_name() == "prop_twosided_radio":
                    althyp_str = ", alternative=\"two.sided\""
                elif radio.get_name() == "prop_greater_radio":
                    althyp_str = ", alternative=\"greater\""
                else:
                    althyp_str = ", alternative=\"less\""
                break
        
        conflevel = conflevel_entry.get_text()
        if conflevel == "":
            error.show_error("Proportions Test (stats)", "You must enter a confidence level.")
            prop_dialog.hide()
            return prop(data_group)
        try:
            float(conflevel)
        except:
            error.show_error("Proportions Test (stats)", "Confidence level must be between 0 and 1")
            prop_dialog.hide()
            return prop(data_group)
        if float(conflevel) <= 0 or float(conflevel) >= 1:
            error.show_error("Proportions Test (stats)", "Confidence level must be between 0 and 1")
            prop_dialog.hide()
            return prop(data_group)
        conflevel_str = ", conf.level=%s"%conflevel
        
        correct = correct_check.get_active()
        correct_str = ", correct=%s"%str(correct).upper()
        
        if use_trials:
            command["pre"] = setup_str
            command["main"] = "prop.test(succ,trials%s%s%s%s)"%(prob_str,\
                althyp_str,conflevel_str, correct_str)
            command["post"] = cleanup_str
        else:
            command["pre"] = ""
            command["main"] = "prop.test(matrix(c(%s,%s), ncol=2)%s%s%s%s)"%(data1,\
                data2, prob_str, althyp_str, conflevel_str, correct_str)
            command["post"] = ""
    else:
        command["pre"] = ""
        command["main"] = ""
        command["post"] = ""
    prop_dialog.hide()
    return command
        

def compatible_funcs(data_group):
    func_list = []
    member_dict = data_group.member_dict
    member_list = data_group.member_list
    #Linear Model:
    if member_dict.get("Response") == 1 and \
        (member_dict.get("Fixed Factor") >= 1 or
        member_dict.get("Covariate") >= 1):
            add_func = True
            for member in member_list:
                if member.role == "Response" and member.aux == "Unknown":
                    add_func = False
            if add_func:
                func_list.append(["Linear Model", "Build a linear model", lm])
    #Student's t-test
    if (member_dict.get("Response") == 1 and \
        member_dict.get("Fixed Factor") == 1 and \
        member_dict.get("Sample Data") == None) or \
        member_dict.get("Sample Data") == 2 or \
        (member_dict.get("Sample Data") == 1 and \
        member_dict.get("Fixed Factor") == 1 and \
        member_dict.get("Response") == None):
            add_func = True
            for member in member_list:
                if member.role == "Response" and member.aux != "Normal":
                    add_func = False
                else:
                    if member.role == "Fixed Factor" and len(member.aux) != 2:
                        add_func = False
            if add_func:
                func_list.append(["Student's T-test", "Comparison of means", t_test])
    #AIC
    if member_dict.get("Linear Model") == 1:
        func_list.append(["AIC", "Akaike's An Information Criterion", aic])
    #Alias
    if member_dict.get("Linear Model") == 1:
        func_list.append(["Alias", "Find aliases (dependencies) in a model", alias])
    #Bartlett Test
    if (member_dict.get("Response") == 1 and \
        member_dict.get("Fixed Factor") == 1 and
        member_dict.get("Sample Data") == None) or \
        member_dict.get("Sample Data") > 1 or \
        (member_dict.get("Sample Data") == 1 and \
        member_dict.get("Fixed Factor") == 1 and \
        member_dict.get("Response") == None):
        func_list.append(["Bartlett Test", "Test for homogeneity of variances", bartlett])
    #ANOVA
    if member_dict.get("Linear Model") >= 1:
        func_list.append(["ANOVA", "Analysis of variance", anova])    
    #Pearson's Chi-squared test
    if member_dict.get("Fixed Factor") == 1 or \
        member_dict.get("Fixed Factor") == 2 or \
        member_dict.get("Counts") >= 1:
            func_list.append(["Pearson's Chi-squared Test", "Chi-squared contingency table test or goodness-of-fit test",\
            pearson])
    #Fisher's Test
    if member_dict.get("Fixed Factor") == 2 or \
        member_dict.get("Counts") >= 2:
            func_list.append(["Fisher Test", "Fisher's Exact Test for count data",\
            fisher])
    #Five Number Summary
    if member_dict.get("Sample Data") == 1:
        func_list.append(["Five Number Summary", "Tukey five-number summary", \
        fivenum])
    #Fligner Test
    if (member_dict.get("Sample Data") > 1 and \
        member_dict.get("Fixed Factor") == None) or \
        (member_dict.get("Response") == 1 and \
        member_dict.get("Fixed Factor") == 1 and \
        member_dict.get("Sample Data") == None) or \
        (member_dict.get("Sample Data") == 1 and \
        member_dict.get("Fixed Factor") == 1 and \
        member_dict.get("Response") == None):
            func_list.append(["Fligner-Killeen Test", "Test for homogeneity of variances", \
            fligner])
    #Kruskal-Wallis Test
    if (member_dict.get("Sample Data") > 1 and \
        member_dict.get("Fixed Factor") == None) or \
        (member_dict.get("Response") == 1 and \
        member_dict.get("Fixed Factor") == 1 and \
        member_dict.get("Sample Data") == None) or \
        (member_dict.get("Sample Data") == 1 and \
        member_dict.get("Fixed Factor") == 1 and \
        member_dict.get("Response") == None):
            func_list.append(["Kruskal-Wallis Test", "Rank sum test", \
            kruskal])
    #McNemar's Chi-Squared Test
    if member_dict.get("Fixed Factor") == 2 or \
        member_dict.get("Counts") >= 2:
            add_func = True
            levels = -1
            for member in member_list:
                if member.role == "Counts":
                    if member.n != member_dict.get("Counts"):
                        add_func = False
                elif member.role == "Fixed Factor":
                    if levels == -1:
                        levels = member.aux
                    else:
                        if member.aux != levels:
                            add_func = False
            if add_func == True:
                func_list.append(["McNemar's Chi-Squared Test", "McNemar's Chi-Squared Test for count data",\
                mcnemar])
    #Median
    if (member_dict.get("Sample Data") == 1 and \
        member_dict.get("Response") == None) or \
        (member_dict.get("Response") == 1 and \
        member_dict.get("Sample Data") == None):
            func_list.append(["Median", "Find a median value", median])
    #Mean
    if (member_dict.get("Sample Data") == 1 and \
        member_dict.get("Response") == None) or \
        (member_dict.get("Response") == 1 and \
        member_dict.get("Sample Data") == None):
            func_list.append(["Mean", "Find a mean value", mean])
    #Standard Deviation
    if (member_dict.get("Sample Data") == 1 and \
        member_dict.get("Response") == None) or \
        (member_dict.get("Response") == 1 and \
        member_dict.get("Sample Data") == None):
            func_list.append(["Standard Deviation", "Find the standard deviation of data", sd])    
    #Proportions Test
    if member_dict.get("Counts") == 2:
            func_list.append(["Proportions Test", "Test of equal or given proportions", prop])    
            
    return func_list
                

callbacks = {"on_lm_usesubset_toggled" : on_lm_usesubset,\
        "on_lm_add" : on_lm_add,\
        "on_lm_remove": on_lm_remove,\
        "on_ttest_usesubset_toggled": on_ttest_usesubset, \
        "on_bartlett_usesubset_toggled": on_bartlett_usesubset,\
        "on_pearson_simulate": on_pearson_simulate,\
        "on_fisher_simulate": on_fisher_simulate,\
        "on_fisher_confint": on_fisher_confint}
glade_gui.signal_autoconnect(callbacks)    








